package com.example.coffeeseller_2.widget;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

import com.example.coffeeseller_2.R;


/**
 * Created by WH on 2018/7/12.
 * 波浪视图
 */

public class WaveView extends View {
    private static final String TAG = "WaveView";
    private int defaultWaveHeight = 100;
    private int defaultWaveHalfNum = 2;
    private Context context;
    private int screenWidth;
    private int screenHeight;
    private int baseLine = 0;// 基线，用于控制水位上涨的
    private int waveHeight;// 波浪的最高度
    private int waveWidth;//波长
    private float curOffset = 0f;//偏移量
    private float lastOffset = 0f;
    private float offset = 0f;
    private int waveHalfNum;
    private int baseLineMult;
    private int animTime;
    private int mode;
    private Paint paint;
    private int filledColor;
    private int paintColor;
    private int paintStock;
    private boolean isStop = false;
    private Path mPath;
    private OnInVilidateListenner onInVilidateListenner;
    private Handler handler;


    public WaveView(Context context) {
        super(context);
    }

    public WaveView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public WaveView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private void init(Context context, AttributeSet attrs) {
        this.context = context;
        handler = new Handler();
        TypedArray attrsArray = context.obtainStyledAttributes(attrs, R.styleable.WaveView);
        waveHeight = attrsArray.getInteger(R.styleable.WaveView_waveHeight, defaultWaveHeight);
        offset = attrsArray.getInteger(R.styleable.WaveView_offset, 0);
        paintStock = attrsArray.getInteger(R.styleable.WaveView_paintStock, 1);
        paintColor = attrsArray.getColor(R.styleable.WaveView_paintColor, ContextCompat.getColor(context, R.color.white));
        filledColor = attrsArray.getColor(R.styleable.WaveView_filledColor, ContextCompat.getColor(context, R.color.white));
        waveHalfNum = attrsArray.getInteger(R.styleable.WaveView_waveHalfNum, defaultWaveHalfNum);
        baseLineMult = attrsArray.getInteger(R.styleable.WaveView_baseLineMult, defaultWaveHalfNum);
        animTime = attrsArray.getInteger(R.styleable.WaveView_animTime, waveHalfNum * 1000);
        mode = attrsArray.getInteger(R.styleable.WaveView_mode, 0);//0表示正弦、1表示余弦
        lastOffset = offset;
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setStrokeWidth(paintStock);
        paint.setColor(paintColor);

        onInVilidateListenner = new OnInVilidateListenner() {
            @Override
            public void invalidate(Path path) {
                mPath = path;
                postInvalidate();
            }
        };

    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        screenWidth = getMeasuredWidth();
        screenHeight = getMeasuredHeight();

        waveWidth = screenWidth;
        baseLine = waveHeight * baseLineMult;
        new Thread(new Runnable() {
            @Override
            public void run() {

                updateXControl();
            }
        }).start();

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (mPath != null) {
            canvas.drawPath(mPath, paint);
        }

    }

    private Path getPath2() {
        mPath = new Path();
        float itemWidth = ((float) waveWidth) / waveHalfNum;//半个波长
        if (mode % 2 == 0) {
            //  mPath.moveTo(itemWidth * -(waveHalfNum * 2), baseLine);//起始坐标 itemWidth * -(waveHalfNum * 2)
            mPath.moveTo(-itemWidth, baseLine);//起始坐标 itemWidth * -(waveHalfNum * 2)
            //核心的代码就是这里
            for (int i = -2; i < waveHalfNum + 1; i++) {//waveHalfNum * 2
                float startX = i * itemWidth + curOffset;

                float controlX = startX + itemWidth / 2;
                float endX = startX + itemWidth;
                mPath.quadTo(
                        controlX,//控制点的X,（起始点X + itemWidth/2 + offset)
                        getWaveHeigh(i),//控制点的Y
                        endX,//结束点的X
                        baseLine//结束点的Y
                );//只需要处理完半个波长，剩下的有for循环自已就添加了。
            }
        } else {
//            mPath.moveTo(itemWidth * -(waveHalfNum * 2), baseLine);//起始坐标  //-(waveHalfNum* 2) :采用这种没有明显的抖动效果，4个半波峰的时候
            mPath.moveTo(itemWidth * -1, baseLine);//起始坐标  //-(waveHalfNum* 2) :采用这种没有明显的抖动效果，4个半波峰的时候
            //核心的代码就是这里
            for (int i = -2; i < waveHalfNum + 1; i++) {//waveHalfNum * 2
                float startX = i * itemWidth + itemWidth + lastOffset;
                mPath.quadTo(
                        startX + itemWidth / 2 + curOffset,//控制点的X,（起始点X + itemWidth/2 + offset)
                        getWaveHeigh(i),//控制点的Y
                        startX + itemWidth + curOffset,//结束点的X
                        baseLine//结束点的Y
                );//只需要处理完半个波长，剩下的有for循环自已就添加了。
            }
        }

        //下面这三句话很重要，它是形成了一封闭区间，让曲线以下的面积填充一种颜色，大家可以把这3句话注释了看看效果。
        mPath.lineTo(screenWidth, screenHeight);
        mPath.lineTo(0, screenHeight);
        mPath.close();
        return mPath;
    }

    int count = 0;

    //奇数峰值是正的，偶数峰值是负数
    private int getWaveHeigh(int num) {
        if (num % 2 == 0) {
            return baseLine + waveHeight;
        }
        return baseLine - waveHeight;
    }

    /**
     * 不断的更新偏移量，并且循环。
     */
    private void updateXControl() {
        float itemWidth = ((float) waveWidth) / waveHalfNum;//半个波长
        float width = waveWidth;
        if (itemWidth * waveHalfNum < waveWidth) {
            width = (waveHalfNum) * itemWidth * 2;//(waveHalfNum) * itemWidth * 2
        } else {
            width = waveHalfNum * itemWidth;
        }
        //设置一个波长的偏移
        final ValueAnimator mAnimator = ValueAnimator.ofFloat(0, width);
        mAnimator.setInterpolator(new LinearInterpolator());
        mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float animatorValue = (float) animation.getAnimatedValue();
                curOffset = lastOffset + animatorValue;//不断的设置偏移量，并重画
                if (onInVilidateListenner != null) {
                    onInVilidateListenner.invalidate(getPath2());

                }
                //  postInvalidate();
            }
        });
        mAnimator.setDuration(animTime);
        mAnimator.setRepeatCount(ValueAnimator.INFINITE);//ValueAnimator.INFINITE
        handler.post(new Runnable() {
            @Override
            public void run() {
                mAnimator.start();

            }
        });
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        clearAnimation();
    }

    public int getBaseLine() {
        return baseLine;
    }

    public int getWaveHeight() {
        return waveHeight;
    }

    public float getOffset() {
        return curOffset;
    }

    public Paint getPaint() {
        return paint;
    }

    interface OnInVilidateListenner {
        void invalidate(Path path);
    }
}
